home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / dos / secmpeg3 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  14.0 KB  |  610 lines

  1.  
  2. /* --- C ---
  3. ************************************************************************
  4. *
  5. *    Filename    : main.c
  6. *    Description : Main-module - command parser
  7. *    Part of     : SECMPEG
  8. *
  9. *    Version     : 1.0
  10. *    Language    : C
  11. *    For machine : SunOS 4.1.x, INTERACTIVE Unix 2.2.1, Linux, MS-DOS
  12. *    Compile as  : see Makefile
  13. *
  14. *    Authors     : Juergen Meyer, Frank Gadegast
  15. *    Contact     : jm@cs.tu-berlin.de, phade@cs.tu-berlin.de
  16. *
  17. ************************************************************************
  18. */
  19. #include "version.h"
  20. #define NEED_ERRORS
  21. #include "defs.h"
  22. #undef NEED_ERRORS
  23.  
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #ifdef DOSTIME
  28. #include <time.h>
  29. #include <dos.h>
  30. #else
  31. #include <sys/timeb.h>
  32. #endif
  33.  
  34.  
  35. /* ------ PUBLIC ------ */
  36. int                   main (int,char **);
  37. int                   EncryptMpeg();
  38. int                   DecryptSecMpeg();
  39. int                   error_exit ();
  40.  
  41.  
  42. /* ------ PRIVAT ------ */
  43. static int            ProcessFrame(int,unsigned long);
  44.  
  45. static int            GetNumberOfMakroBlocks();
  46. static int            GetAverageMakroBlockSize(int,unsigned long);
  47. static int            CheckIntraFrameSize(int,unsigned long);
  48. static int            parse_commandline(int,char **);
  49. static void           usage();
  50.  
  51.  
  52. /* ------ IMPORT ------ */
  53. extern int           InitMemory();                      /* stream.c */
  54. extern int           FreeMemory();
  55. extern int           OpenInputStream(char *);
  56. extern int           OpenOutputStream(char *);
  57. extern void          CloseStreams();
  58. extern int           WriteStream();
  59. extern int           ReadStream(unsigned long);
  60. extern void          CopyBuffer();
  61.  
  62. extern int           ReadPictureHeader();               /* header.c */
  63. extern int           DecodeFrame();                     /* decode.c */
  64.  
  65. extern int           WriteSecureMpegHeader();           /* sec.c */
  66. extern int           WriteSecureMpegInfo();
  67. extern int           ReadSecureMpegHeader();
  68. extern int           ReadSecureMpegInfo();
  69. extern unsigned long GetPictureHeader(int);
  70. extern int           EncryptFrame(int,unsigned long);
  71. extern int           DecryptFrame(int,unsigned long);
  72. extern int           SetTableEntries(int,unsigned long);
  73. extern int           CryptStream ();
  74. extern int           CrcStream ();
  75.  
  76. extern int           desinit();                         /* des.c */
  77. extern void          desdone();
  78. extern int           Encrypt(char *,unsigned long);
  79. extern int           Decrypt(char *,unsigned long);
  80. extern char          *string_to_key(char *);
  81. extern void          setdeskey(char *);
  82.  
  83. extern int           InitHuffman();                     /* huff.c */
  84. extern void          FreeHuffTables();
  85.  
  86. extern BYTE          *frame_buffer;                     /* stream.c */
  87.  
  88. extern unsigned long crc16buf ();                       /* crc.c */
  89. extern unsigned long crc32buf ();                       /* crc.c */
  90.  
  91. /* ------ VARS ------ */
  92. char                 *progname;
  93. char                 deskey[9];
  94. char                 input_stream[128];
  95. char                 output_stream[128];
  96. short                ENCODE = 0;
  97. int                  WRITE = TRUE;
  98. int                  VERBOSE = TRUE;
  99.  
  100. int                  MBcount;
  101. int                  c_level = -1;
  102. int                  i_level = -1;
  103. int                  c_table_entries;
  104. SECUREHEADER         sec_header;
  105. SECUREINFO           sec_info;
  106. INTEGRTABLE          i_table [1];
  107. SECURETABLE          c_table [MAX_MB];
  108.  
  109. extern int           end_of_file;                       /* stream.h */
  110. extern unsigned long total_bytes_read;
  111. extern unsigned long total_bytes_written;
  112.  
  113. extern int           HorizontalSize;                    /* header.h */
  114. extern int           VerticalSize;
  115.  
  116. extern int           MBHeight;                          /* decode.h */
  117. extern int           MBWidth;
  118.  
  119. extern long          mvalue;                            /* sec.c */
  120.  
  121. int    main(int argc, char **argv)
  122. {
  123.     int retval;
  124.  
  125. #ifdef DOSTIME
  126.     time_t          t1,t2;
  127.     extern unsigned _stklen;
  128.  
  129.     _stklen = 4 * 1024;
  130. #else
  131.     struct timeb    t1,t2;
  132.     time_t          sec;
  133.     unsigned short  msec;
  134. #endif
  135.  
  136.  
  137. #ifdef DEBUG
  138.     fprintf(stderr," %s \n","secure_mpeg");
  139. #endif
  140.  
  141.     if (!parse_commandline (argc, argv))
  142.     {
  143.         usage ();
  144.         error_exit (ERROR_USAGE);
  145.     }
  146.  
  147.     retval = desinit();
  148.     if (retval < 0) error_exit (retval);
  149.     retval = InitHuffman();
  150.     if (retval < 0) error_exit (retval);
  151.     retval = InitMemory();
  152.     if (retval < 0) error_exit (retval);
  153.  
  154.     retval = OpenInputStream (input_stream);
  155.     if (retval < 0) error_exit (ERROR_OPEN_INPUT);
  156.     if (WRITE)
  157.     {
  158.         retval = OpenOutputStream (output_stream);
  159.         if (retval < 0) error_exit (ERROR_OPEN_OUTPUT);
  160.     }
  161.  
  162.     setdeskey (deskey);
  163.  
  164. #ifdef TIME
  165. #ifdef DOSTIME
  166.     t1 = clock();
  167. #else
  168.     ftime(&t1);
  169. #endif
  170. #endif
  171.  
  172.     retval  = ERROR_NOTHING_TODO;
  173.     switch (ENCODE)
  174.     {
  175.         case M_ENCODE :
  176.             retval = EncryptMpeg ();
  177.             break;
  178.         case M_DECODE :
  179.             retval = DecryptSecMpeg();
  180.             break;
  181.         case M_VALUE :
  182.             retval = CrcStream ();
  183.             break;
  184.         case M_CENCRYPT :
  185.         case M_CDECRYPT :
  186.             retval = CryptStream (ENCODE);
  187.             break;
  188.     }
  189.     if (retval != ERROR_NONE) error_exit (retval);
  190.  
  191. #ifdef TIME
  192. #ifdef DOSTIME
  193.     t2 = clock();
  194.     if (VERBOSE)
  195.         fprintf (stderr,
  196.             "%s elapsed time %f sec.\n", progname, (t2-t1)/CLK_TCK);
  197. #else
  198.     ftime(&t2);
  199.     sec = t2.time - t1.time;
  200.     msec = (1000 - t1.millitm)+t2.millitm;
  201.     if (msec > 1000) msec -= 1000;
  202.     else sec--;
  203.     
  204.     if (VERBOSE)
  205.     {
  206.         if ((!WRITE) && (ENCODE != M_VALUE))
  207.             fprintf (stderr, "%s: elapsed time %d.%d sec. CRC-check ok.\n",
  208.                 progname, sec, msec);
  209.         else
  210.             if (ENCODE == M_VALUE)
  211.                 fprintf (stderr, "%s: elapsed time %d.%d sec. CRC = %ld\n",
  212.                     progname, sec, msec, mvalue);
  213.             else
  214.                 fprintf (stderr,
  215.                     "%s: elapsed time %d.%d sec.\n", progname, sec, msec);
  216.     }
  217.      
  218. #endif
  219. #endif
  220.     desdone();
  221.     FreeHuffTables();
  222.     FreeMemory();
  223.  
  224.     return (ERROR_NONE);
  225. }
  226.  
  227.  
  228. int    EncryptMpeg()
  229. {
  230.     unsigned long  offset;
  231.     unsigned long  header_size;
  232.     int            picture_type;
  233.     int            i;
  234.     int            frame = 0;
  235.     int            makroblocks;
  236.  
  237.     do
  238.     {
  239.         if (!frame++)
  240.         {
  241.             WriteSecureMpegHeader();
  242.             offset = GetPictureHeader (0);        /* PSC in marker.h */
  243.             if (!offset) return (ERROR_MARKER_STRUCTURE );
  244.             CopyBuffer ();
  245.             MBcount = GetNumberOfMakroBlocks();
  246.             if (MBcount > MAX_MB) return (ERROR_NO_MPEGI);
  247.             sec_info.IntegrityDataSize = -1;  /*  nicht vorhanden */
  248.             sec_info.ConfidentialityDataSize = 0;   /*  alle Daten bis zum naechsten Header */
  249.             sec_info.NextHeader = offset;
  250.             WriteSecureMpegInfo();
  251.             if (c_level > -1) EncryptFrame (0, offset);
  252.             WriteStream ();
  253.         }
  254.  
  255.         offset = GetPictureHeader(1);
  256.         if(offset) CopyBuffer();            /* copy bits into frame_buffer */
  257.  
  258.         picture_type = ReadPictureHeader();
  259.  
  260.  
  261. #ifdef DEBUG
  262.  
  263.         switch(picture_type)
  264.         {
  265.             case P_PREDICTED:
  266.                 fprintf (stderr,
  267.                     "Frame : %.3d PREDICTED FRAME    Size : %.5lu\n",
  268.                     frame,offset);
  269.                 break;
  270.             case P_DCINTRA:
  271.                 fprintf (stderr,
  272.                     "Frame : %.3d DC-INTRA FRAME     Size : %.5lu\n",
  273.                     frame,offset);
  274.                 break;
  275.             case P_INTRA:
  276.                 fprintf (stderr,
  277.                     "Frame : %.3d INTRA FRAME        Size : %.5lu\n",
  278.                     frame,offset);
  279.                 break;
  280.             case P_INTERPOLATED:
  281.                 printf (stderr,
  282.                     "Frame : %.3d INTERPOLATED FRAME Size : %.5lu\n",
  283.                     frame,offset);
  284.             break;
  285.             default:
  286.                 /*
  287.                 picture_type = P_INTRA;
  288.                 fprintf (stderr,
  289.                     "Frame : %.3d UNKNOWN FRAME      Size : %.5lu now INTRA\n",
  290.                     frame,offset);
  291.                 break;
  292.                 */
  293.                 return(picture_type);
  294.         }
  295. #else
  296.         if(picture_type < 0) return(picture_type);
  297. #endif
  298.  
  299.         ProcessFrame(picture_type,offset);     
  300.         WriteStream();
  301.     }
  302.     while(!end_of_file);
  303.  
  304.  
  305.     sec_info.IntegrityDataSize       = -1;
  306.     sec_info.ConfidentialityDataSize = -1;
  307.     sec_info.NextHeader              =  0; /*  end_of_file marker */
  308.     WriteSecureMpegInfo();
  309.     return (ERROR_NONE);
  310. }
  311.  
  312. int    DecryptSecMpeg()
  313. {
  314.     unsigned long  offset;
  315.     int            retval;
  316.     int            first_frame = 1;
  317.     int            i;
  318.     int            crc;
  319.  
  320.     do
  321.     {
  322.         if(first_frame)
  323.         {
  324.             retval = ReadSecureMpegHeader();
  325.             if (retval < 0) error_exit (ERROR_NO_MPEGHEADER);
  326.             retval = ReadSecureMpegInfo();
  327.             if (retval < 0) error_exit (ERROR_NO_MPEGINFO);
  328.             offset = sec_info.NextHeader;
  329.             retval = ReadStream (offset);
  330.             if (retval < 0) error_exit (ERROR_STREAM);
  331.             if (c_level > -1) DecryptFrame(0,offset);
  332.             WriteStream();
  333.  
  334.             retval = ReadSecureMpegInfo();
  335.             if (retval < 0) error_exit (ERROR_NO_MPEGINFO);
  336.             offset = sec_info.NextHeader;
  337.             first_frame--;
  338.         }
  339.         retval = ReadStream (offset);
  340.         if (retval < 0) error_exit (ERROR_STREAM);
  341.        
  342.         if (c_level > -1) DecryptFrame(sec_info.ConfidentialityDataSize,offset);
  343.         if (i_level > -1)
  344.         {
  345.             switch (i_level)
  346.             {
  347.                 case I_CRC16 :
  348.                     crc = crc16buf ((char *)frame_buffer, (unsigned long) 24);
  349.                     break;
  350.                 case I_CRC16FULL :
  351.                     crc = crc16buf ((char *)frame_buffer, i_table[0].len);
  352.                     break;
  353.                 case I_CRC32 :
  354.                     crc = crc32buf ((char *)frame_buffer, (unsigned long) 24);
  355.                     break;
  356.                 case I_CRC32FULL :
  357.                     crc = crc32buf ((char *)frame_buffer, i_table[0].len);
  358.                     break;
  359.                 default:
  360.                     error_exit (ERROR_INOTSUPPORTED);
  361.                     break;
  362.             }
  363.             if (crc != i_table[0].crc)
  364.                 error_exit (ERROR_CRCFAILED);
  365.         }
  366.         WriteStream();
  367.  
  368.         retval = ReadSecureMpegInfo();
  369.         if (retval < 0) error_exit (ERROR_NO_MPEGINFO);
  370.         offset = sec_info.NextHeader;
  371.  
  372.     }
  373.     while (!end_of_file);
  374.     return (ERROR_NONE);
  375. }
  376.  
  377.  
  378. static int ProcessFrame (int picture_type,unsigned long frame_len)
  379. {
  380.     int c_size;
  381.     int mb_size = 0;
  382.  
  383.     sec_info.NextHeader = frame_len;
  384.  
  385.     if (i_level > -1)
  386.     {
  387.         switch (i_level)
  388.         {
  389.             case I_CRC16 :
  390.                 i_table[0].crc =
  391.                     crc16buf ((char *)frame_buffer, (unsigned long) 24);
  392.                 i_table[0].len = (unsigned long) 24;
  393.                 break;
  394.             case I_CRC16FULL :
  395.                 i_table[0].crc = crc16buf ((char *)frame_buffer, frame_len);
  396.                 i_table[0].len = frame_len;
  397.                 break;
  398.             case I_CRC32 :
  399.                 i_table[0].crc =
  400.                     crc32buf ((char *)frame_buffer, (unsigned long) 24);
  401.                 i_table[0].len = (unsigned long) 24;
  402.                 break;
  403.             case I_CRC32FULL :
  404.                 i_table[0].crc = crc32buf ((char *)frame_buffer, frame_len);
  405.                 i_table[0].len = frame_len;
  406.                 break;
  407.             default:
  408.                 error_exit (ERROR_INOTSUPPORTED);
  409.                 /* no Integrity-checks */
  410.                 break;
  411.         }
  412.     }
  413.  
  414.     c_size = 0;
  415.     if (c_level > -1)
  416.     {
  417.         switch (c_level)
  418.         {
  419.             case C_24BYTE :
  420.                 c_size = 1;
  421.                 c_table[0].Offset = 0;
  422.                 c_table[0].Len = 24;
  423.                 break;
  424.             case C_HEADER :
  425.                 c_size = SetTableEntries(8,frame_len);
  426.                 break;
  427.             case C_HEADERMB :
  428.                 mb_size = GetAverageMakroBlockSize(MBcount,frame_len);
  429.                 c_size = SetTableEntries(mb_size,frame_len);
  430.                 break;
  431.             case C_INTRAHEADERMB :
  432.                 if ((picture_type == P_INTRA) || (picture_type == P_DCINTRA))
  433.                     c_size = 0;
  434.                 else
  435.                 {
  436.                     mb_size = GetAverageMakroBlockSize(MBcount,frame_len);
  437.                     c_size = SetTableEntries(mb_size,frame_len);
  438.                 }
  439.                 break;
  440.             case C_INTRACOMPLETE:
  441.                 if ((picture_type == P_INTRA) || (picture_type == P_DCINTRA))
  442.                     c_size = 0;
  443.                 else
  444.                     c_size = DecodeFrame(c_table, c_table_entries);
  445.                 break;
  446.             default:
  447.                 error_exit (ERROR_CNOTSUPPORTED);
  448.                 break;
  449.         }
  450.         EncryptFrame (c_size,frame_len);
  451.     }
  452.  
  453.     sec_info.IntegrityDataSize       = c_size;
  454.     sec_info.ConfidentialityDataSize = c_size;
  455.     sec_info.NextHeader = frame_len;
  456.     WriteSecureMpegInfo();
  457.     return(TRUE);
  458. }
  459.  
  460.  
  461. /*
  462.     Berechnung der Anzahl der MakroBl÷cke pro Frame,
  463.     wird ben÷tigt zur AbschΣtzung, ob ein Intraframe
  464.     vollstΣndig verschlⁿsselt wird, oder nur Teile
  465.     davon.
  466.     MBWidth und MBHeight mⁿssen berechnet werden, da
  467.     VideoSequence- und GroupOfPicturesHeader nicht
  468.     explizit gelesen werden.
  469.  
  470. */
  471. static int GetNumberOfMakroBlocks()
  472. {
  473.     MBHeight = (VerticalSize   + 15) / 16;
  474.     MBWidth  = (HorizontalSize + 15) / 16;
  475.  
  476.     return(MBHeight * MBWidth);
  477.  
  478. }
  479.  
  480. static int GetAverageMakroBlockSize(int makroblocks,unsigned long frame_len)
  481. {
  482.         int mb_size;
  483.  
  484.         mb_size = (int)(frame_len / makroblocks);
  485.         mb_size += 7;
  486.         mb_size >>= 3;
  487.         mb_size <<=3;
  488.      
  489.         return(mb_size);
  490. }
  491. /*
  492.     AbschΣtzung, ob der Frame vollstΣndig verschlⁿsselt
  493.     werden soll oder nur zum Teil.
  494.  
  495.        avg MB Size Intra         2 Bit
  496.                Predicted    10 Bit
  497.                Interpoleted 16 Bit
  498.        SliceHeader               6 Bit
  499.  
  500.  
  501. */
  502. static  int  CheckIntraFrameSize(int makroblocks,unsigned long framelen)
  503. {
  504.  
  505.     unsigned long  size;
  506.  
  507.     size = framelen - (unsigned long)(makroblocks / 4);
  508.  
  509.     size /= (unsigned long)(makroblocks * 6);
  510.  
  511.     if(size < 16)
  512.        return(TRUE);
  513.     return(FALSE);
  514. }
  515.  
  516.  
  517. static int parse_commandline (int argc, char **argv)
  518. {
  519.     int i;
  520.  
  521.     progname = argv [0];
  522.     if (argc == 2)
  523.         if (!strcmp (argv [1], "-v"))
  524.     {
  525.         fprintf (stderr, "%s: %s\n", progname, version_string);
  526.         exit (0);
  527.     }
  528.     if (argc < 3) return (FALSE);
  529.     for (i=1; i < argc; i++)
  530.     {
  531.         if (argv [i][0] == '-')
  532.         {
  533.             switch (argv[i][1])
  534.             {
  535.                 case 'e' :
  536.                     ENCODE = M_ENCODE;
  537.                     c_level = atoi (argv [++i]);
  538.                     if (c_level > -1)
  539.                         strcpy (deskey, argv [++i]);
  540.                     i_level = atoi (argv [++i]);
  541.                     break;
  542.                 case 'd' :
  543.                     ENCODE = M_DECODE;
  544.                     if (argc == i+4)
  545.                         strcpy (deskey, argv [++i]);
  546.                     break;
  547.                 case 'c' :
  548.                     ENCODE = M_DECODE;
  549.                     WRITE = FALSE;
  550.                     if (argc == i+3)
  551.                         strcpy (deskey, argv [++i]);
  552.                     break;
  553.                 case 's' :
  554.                 case 'S' :
  555.                     VERBOSE = FALSE;
  556.                     break;
  557.                 case 'E' :
  558.                     ENCODE = M_CENCRYPT;
  559.                     strcpy (deskey, argv [++i]);
  560.                     break;
  561.                 case 'D' :
  562.                     ENCODE = M_CDECRYPT;
  563.                     strcpy (deskey, argv [++i]);
  564.                     break;
  565.                 case 'C' :
  566.                     ENCODE = M_VALUE;
  567.                     WRITE = FALSE;
  568.                     break;
  569.                 default :
  570.                     if (strlen (argv[i]) > 1) return (FALSE);
  571.                     break;
  572.             }
  573.         }
  574.     }
  575.  
  576.     strcpy (input_stream, argv [argc-2]);
  577.     strcpy (output_stream, argv [argc-1]);
  578.     if (!WRITE) strcpy (input_stream, output_stream);
  579.  
  580.     sec_header.ConfidentialityInfo = (long) c_level;
  581.     sec_header.IntegrityInfo = (long) i_level;
  582.  
  583.     return (TRUE);
  584. }
  585.  
  586. static void usage()
  587. {
  588.     fprintf (stderr, "usage : %s {-scedCED} [clevel key ilevel] infile.mpg [outfile.mpg]\n", progname);
  589. }
  590.  
  591.  
  592. int    error_exit (exit_code)
  593. int exit_code;
  594. {
  595.     FreeMemory ();
  596.     CloseStreams ();
  597.     desdone ();
  598.     FreeHuffTables ();
  599.     if (exit_code < 0)
  600.     {
  601.         if (strlen (error_msg [abs (exit_code)]) > 1)
  602.             fprintf (stderr, "%s : fatal error '%s'\n",
  603.                 progname, error_msg [abs (exit_code)]);
  604.         else fprintf (stderr, "%s : fatal error\n", progname );
  605.         exit (exit_code);
  606.     }
  607.     exit (exit_code);
  608. }
  609.  
  610.